﻿using MQTTnet;
using MQTTnet.Client.Connecting;
using MQTTnet.Client.Options;
using MQTTnet.Client.Receiving;
using MQTTnet.Extensions.ManagedClient;
using SuperWebSocket;
using System;
using System.Collections.Generic;

namespace Zhaoxi.WebSocketService
{
    class Program
    {
        // 如果直接用MQTT.js文件在Web客户端,来写MQTT的客户端代码有弊端:
        // MQTT服务器地址，用户名、密码、订阅信息完全暴露在前端，即时加密也不是很安全。
        // 这个程序的作用是作为一个中间服务器，连接到MQTT服务器，订阅相关主题，然后把接收到的消息通过WebSocket协议推送给Web前端。

        static void Main(string[] args)
        {
            // 这个服务器向Web前端提供连接
            // 创建MQTT的客户端代码，并且创建WebSocket的服务器   -》
            ConnectMQTT();

            StartWebSocket();

            Console.ReadLine();
        }

        static bool state = false;
        static IManagedMqttClient client = null;
        static void ConnectMQTT()
        {
            // 连接到MQTT服务器
            client = new MqttFactory().CreateManagedMqttClient();
            client.ConnectedHandler = new MqttClientConnectedHandlerDelegate(e =>
            {
                MqttTopicFilter mqttTopicFilter = new MqttTopicFilter();
                mqttTopicFilter.Topic = "d/#";
                mqttTopicFilter.QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce;
                client.SubscribeAsync(mqttTopicFilter);
            });
            //client.DisconnectedHandler
            client.ApplicationMessageReceivedHandler =
                new MqttApplicationMessageReceivedHandlerDelegate(e =>
                {
                    // 接收当前订阅主题下的所有消息
                    // 这个消息需要通过WebSocket进行转发
                    foreach (var item in webSocketSessions)
                    {
                        item.Send(e.ApplicationMessage.ConvertPayloadToString());
                    }
                });

            // IP   Port   Client ID
            // UserName  Password
            IMqttClientOptions clientOptions = new MqttClientOptionsBuilder()
                .WithClientId(Guid.NewGuid().ToString())
                .WithTcpServer("127.0.0.1", 1883)// MQTT的服务器地址
                .WithCredentials("admin", "123456")
                .Build();
            IManagedMqttClientOptions options = new ManagedMqttClientOptionsBuilder()
                .WithClientOptions(clientOptions)
                .Build();

            client.StartAsync(options);// 异步连接到服务器
        }

        static WebSocketServer server = null;
        static List<WebSocketSession> webSocketSessions = new List<WebSocketSession>();
        static void StartWebSocket()
        {
            server = new WebSocketServer();
            // 1、IP
            // 2、端口
            // 3、验证信息
            SuperSocket.SocketBase.Config.ServerConfig s = new SuperSocket.SocketBase.Config.ServerConfig();
            s.MaxConnectionNumber = 1024;
            s.Ip = "0.0.0.0";
            s.Port = 9090;
            server.Setup(s);

            server.Start();
            Console.WriteLine("WebSocket 服务已启动");

            // 监听连接  当有新连接进来的时候，触发这个事件
            server.NewSessionConnected += Server_NewSessionConnected;
        }
        static void Server_NewSessionConnected(WebSocketSession session)
        {
            webSocketSessions.Add(session);
            Console.WriteLine($"[WebSocket]有客户端接入：{session.SessionID}");
        }
    }
}
